package com.twq.oo.abstractscls.third

/**
 * Created by tangweiqun on 2017/11/28.
 *
 */
abstract class Element {
  def contents: Array[String]

  def width: Int = contents(0).length

  def height: Int =
    if (height == 0) 0 else contents(0).length

  def demo() = {
    println("Element's implementation invoked")
  }
}

class ArrayElement(
                    val contents: Array[String]
                  ) extends Element {
  override def demo() = {
    println("ArrayElement's implementation invoked")
  }
}

class LineElementOld(s: String) extends ArrayElement(Array(s)) {
  override def width = s.length

  override def height = 1

  override def demo() = {
    println("LineElement's implementation invoked")
  }
}

//4、使用复合而不是继承
//继承和复合都是使得一个新的类和其他的类发生关系的方法，
// 如果用这两种方式只是为了单纯的代码复用，用复合比继承要好，
// 继承的时候有个问题，就是当父类改变的时候，很容易影响到子类
//我们在确定两个类是否是继承关系的时候，我们需要确定一个问题，就是"is a"的关系
//我们定义LineElement继承ArrayElement只是为了复用contents的方法代码
//所以这里使用复用会比继承好点
class LineElement(s: String) extends Element {
  val contents = Array(s)

  override def width = s.length

  override def height = 1
}

//1、再定义一个Element的子类，表示指定宽度和高度来填充指定的字符
class UniformElement(
                      ch: Char,
                      override val width: Int,
                      override val height: Int
                    ) extends Element {
  private val line = ch.toString * width

  def contents = Array.fill(height)(line)
}

object Spiral {
  def main(args: Array[String]): Unit = {
    //2、多态
    val e1: Element = new ArrayElement(Array("hello", "world"))
    val ae: ArrayElement = new LineElementOld("hello")
    val e2: Element = ae
    val e3: Element = new UniformElement('x', 2, 3)

    //3、动态绑定
    invokeDemo(e1)
    invokeDemo(ae)
    invokeDemo(e3)
  }

  def invokeDemo(e: Element) = {
    e.demo()
  }
}